
#ifndef RTHTTPAUTHINFOGETTER_H
#define RTHTTPAUTHINFOGETTER_H

#include "RtStdCpp.h"
#include "RtUtilTemplates.h"
#include "RtConditionVariable.h"
#include "RtMutex.h"
#include <vector>

class IRtObserver;
class IRtEventQueue;

/* why we don't let IWbxautoInfoGetter callback to our module, because it will
 cause our program complex.*/
class /*RT_API_EXPORT*/ IRtHttpAuthInfoGetter
{
public:
	enum GETTER_RESULT {
		GETTER_OK = 1, 
		GETTER_CANCEL, 
		GETTER_INTEREPT, 
		GETTER_FAILURE, 
		GETTER_WOULDBLOCK
	};

	class CObserverBuffer 
	{
	public:
		CObserverBuffer(GETTER_RESULT aResult, 
						const CRtString &aUserName, 
						const CRtString &aPassword)
			: m_Result(aResult)
			, m_strUserName(aUserName)
			, m_strPassword(aPassword)
		{
		}
		
		GETTER_RESULT m_Result;
		CRtString m_strUserName;
		CRtString m_strPassword;
	};

	// the function is synchronised and can be blocked
	// aType is 0 means basic/digest auth, 1 means NTLM auth
	// returned value is WBX_OK means OK, and aUserName, aPassword are filled
	// WBX_CANCEL means Cannel, WBX_INTEREPT means Ended by EndAuthModalDlg(),
	// WBX_FAILURE means something wrong.
	virtual GETTER_RESULT GetAuthInfoBlocked(
		/* IN */  const CRtString &aShow, 
		/* IN */  int aType,
		/* OUT */ CRtString &aUserName, 
		/* OUT */ CRtString &aPassword, 
		/* IN */  IRtObserver *aObserver) = 0;

	// the timer will call it to force GetAuthInfoBlocked() to return.
	virtual void InterruptGetAuthInfoBlocked(IRtObserver *aObserver) =0;

	virtual ~IRtHttpAuthInfoGetter() { }
};


#ifdef RT_WIN32

class CRtHttpAuthInfoGetterWin32 : public IRtHttpAuthInfoGetter
{
public:
	static CRtHttpAuthInfoGetterWin32* Instance();

	virtual GETTER_RESULT GetAuthInfoBlocked(
		/* IN */  const CRtString &aShow, 
		/* IN */  int aType,
		/* OUT */ CRtString &aUserName, 
		/* OUT */ CRtString &aPassword, 
		/* IN */  IRtObserver *aObserver);

	virtual void InterruptGetAuthInfoBlocked(IRtObserver *aObserver);

	static LRESULT StartDialogProc(HWND hWnd, UINT uMsg,
		WPARAM wParam, LPARAM lParam);

	RtResult CancelResolve(IRtObserver *aObserver);

private:
	CRtHttpAuthInfoGetterWin32();
	virtual ~CRtHttpAuthInfoGetterWin32();
	
	GETTER_RESULT DoGetAuthInfo_i(
		/* IN */  const CRtString &aShow, 
		/* IN */  int aType,
		/* OUT */ CRtString &aUserName, 
		/* OUT */ CRtString &aPassword);

	RtResult DoCallback_i(GETTER_RESULT aResult);

private:
	CRtString m_strUserName;
	CRtString m_strPassword;
	CRtString m_strHostAndPort;
	CRtString m_strRealm;
	DWORD m_nTypeIDD;
	HWND m_pDlgHwnd;

	typedef CRtMutexThread MutexType;
	MutexType m_Mutex;
	typedef std::vector<std::pair<IRtObserver *, IRtEventQueue *> > ObserversType;
	ObserversType m_Observers;

	friend class CRtSingletonT<CRtHttpAuthInfoGetterWin32>;
	friend class CRtAuthInfoGetterWin32DialogRequestEvent;
	friend class CRtAuthInfoGetterWin32DialogResponseEvent;
};

class CRtAuthInfoGetterWin32DialogRequestEvent : public IRtEvent
{
public:
	CRtAuthInfoGetterWin32DialogRequestEvent(
		const CRtString &aShow, 
		int aType, 
		IRtObserver *aObserver, 
		IRtEventQueue *aEventQueue);

	virtual ~CRtAuthInfoGetterWin32DialogRequestEvent();

	virtual RtResult OnEventFire();

private:
	CRtString m_strShow;
	int m_nType;
	IRtObserver *m_pObserver;
	IRtEventQueue *m_pEventQueue;
};

class CRtAuthInfoGetterWin32DialogResponseEvent : public IRtEvent
{
public:
	CRtAuthInfoGetterWin32DialogResponseEvent(
		IRtObserver *aObserver, 
		IRtHttpAuthInfoGetter::GETTER_RESULT aResult, 
		IRtEventQueue *aEventQueue);

	virtual ~CRtAuthInfoGetterWin32DialogResponseEvent();

	virtual RtResult OnEventFire();

private:
	IRtObserver *m_pObserver;
	IRtHttpAuthInfoGetter::GETTER_RESULT m_Result;
	IRtEventQueue *m_pEventQueue;
};

#endif // RT_WIN32

class /*RT_API_EXPORT*/ CRtHttpAuthInfoGetterByUpperLayer : public IRtHttpAuthInfoGetter
{
public:
	static CRtHttpAuthInfoGetterByUpperLayer* Instance();

	virtual GETTER_RESULT GetAuthInfoBlocked(
		/* IN */  const CRtString &aShow, 
		/* IN */  int aType,
		/* OUT */ CRtString &aUserName, 
		/* OUT */ CRtString &aPassword, 
		/* IN */  IRtObserver *aObserver);

	virtual void InterruptGetAuthInfoBlocked(IRtObserver *aObserver);

	void RegisterNotifaction(IRtObserver *aObserver);

	void SetUserNameAndPassword(
		const CRtString &aUserName, 
		const CRtString &aPassword);

private:
	CRtHttpAuthInfoGetterByUpperLayer();
	virtual ~CRtHttpAuthInfoGetterByUpperLayer();
	
	CRtString m_strUserName;
	CRtString m_strPassword;
	IRtObserver *m_pObserver;
	CRtEventThread m_Event;
	BOOL m_bNeedInterrupt;

	friend class CRtSingletonT<CRtHttpAuthInfoGetterByUpperLayer>;
};

//typedef CRtSingletonT<CRtHttpAuthInfoGetterByUpperLayer> CRtHttpAuthInfoGetterByUpperLayerSingleton;

#endif //!RTHTTPAUTHINFOGETTER_H
